#include "mdatetime.h"

#ifdef Q_OS_WIN
// windows系统
#pragma comment(lib, "winmm.lib")
#include <Windows.h>
#include <MMSystem.h>
#elif defined(Q_OS_LINUX)
// linux系统 后续用到的时候再补充
#elif defined(Q_OS_MAC)
// mac系统 后续用到的时候再补充
#endif

extern QMutex _MDateTime_Mutex;
extern LARGE_INTEGER _MDateTime_litmp;
extern qint64 _MDateTime_PerformanceFrequency;
extern qint64 _MDateTime_PerformanceStartCount;
extern qint64 _MDateTime_PerformancestartDateTime_ns = (QDateTime::currentMSecsSinceEpoch()*1000000); // 纳秒
extern qint64 _MDateTime_PerformancestartDateTime_us = (QDateTime::currentMSecsSinceEpoch()*1000);    // 微秒
extern qint64 _MDateTime_PerformancestartDateTime_ms = (QDateTime::currentMSecsSinceEpoch());         // 毫秒

MDateTime::MDateTime() : QDateTime() {}
MDateTime::MDateTime(MDateTime &other) : QDateTime(other.date(), other.time(), other.timeSpec()), m_time(other.time()) {}
MDateTime::MDateTime(QDateTime &other) : QDateTime(other), m_time(other.time()) {}
// MDateTime::MDateTime(QDate &date) : QDateTime(date) {}
// MDateTime::MDateTime(QDate &date, MTime &time, Qt::TimeSpec spec) : QDateTime(date, time, spec), m_time(time) {}
MDateTime::MDateTime(MDate &date, MTime &time, Qt::TimeSpec spec) : QDateTime(date, time, spec), m_time(time) {}
MDateTime::MDateTime(QDate &date, QTime &time, Qt::TimeSpec spec) : QDateTime(date, (QTime)time, spec), m_time(time) {}

//设置系统日期
bool MDateTime::setSystemDate    ( int year,  int month ,  int day)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wYear    = year;
    systemDateTime.wMonth   = month;
    systemDateTime.wDay     = day;

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QDateTime dt(QDate(year,month,day),QTime::currentTime());
    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}

//设置系统时间
bool MDateTime::setSystemTime    ( int hour,  int minute ,  int second, int msec)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wHour    = hour;
    systemDateTime.wMinute  = minute;
    systemDateTime.wSecond  = second;
    systemDateTime.wMilliseconds = msec;

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QDateTime dt(QDate::currentDate(), QTime(hour, minute, second, msec));
    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}

//设置系统日期时间
bool MDateTime::setSystemDateTime( int year , int month , int day , int hour , int minute , int second , int msec )
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wYear    = year;
    systemDateTime.wMonth   = month;
    systemDateTime.wDay     = day;
    systemDateTime.wHour    = hour;
    systemDateTime.wMinute  = minute;
    systemDateTime.wSecond  = second;
    systemDateTime.wMilliseconds = msec;

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QDateTime dt(QDate(year,month,day),QTime(hour, minute, second, msec));
    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}
//设置系统日期时间  ----重载
bool MDateTime::setSystemDateTime( QDateTime& dt)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wYear    = dt.date().year();
    systemDateTime.wMonth   = dt.date().month();
    systemDateTime.wDay     = dt.date().day();
    systemDateTime.wHour    = dt.time().hour();
    systemDateTime.wMinute  = dt.time().minute();
    systemDateTime.wSecond  = dt.time().second();
    systemDateTime.wMilliseconds = dt.time().msec();

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}
//设置系统日期时间  ----重载
bool MDateTime::setSystemDateTime( MDateTime& dt)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wYear    = dt.date().year();
    systemDateTime.wMonth   = dt.date().month();
    systemDateTime.wDay     = dt.date().day();
    systemDateTime.wHour    = dt.time().hour();
    systemDateTime.wMinute  = dt.time().minute();
    systemDateTime.wSecond  = dt.time().second();
    systemDateTime.wMilliseconds = dt.time().msec();

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}
//设置系统日期的年
bool MDateTime::setSystemYear    ( int year)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wYear    = year;

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QDate date = QDate::currentDate();
    QDateTime dt(QDate(year,date.month(),date.day()),QTime::currentTime());

    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}

//设置系统日期的月
bool MDateTime::setSystemMonth   ( int month)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wMonth   = month;

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QDate date = QDate::currentDate();
    QDateTime dt(QDate(date.year(),month,date.day()),QTime::currentTime());
    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}

//设置系统日期的日
bool MDateTime::setSystemDay     ( int day)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wDay     = day;

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QDate date = QDate::currentDate();
    QDateTime dt(QDate(date.year(),date.month(),day),QTime::currentTime());
    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}

//设置系统日期的时
bool MDateTime::setSystemHour    ( int hour)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wHour    = hour;

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QTime time = QTime::currentTime();
    QDateTime dt(QDate::currentDate(),QTime(hour, time.minute(), time.second(), time.msec()));
    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}

//设置系统日期的分
bool MDateTime::setSystemMinute  ( int minute)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wMinute  = minute;

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QTime time = QTime::currentTime();
    QDateTime dt(QDate::currentDate(),QTime(time.hour(), minute, time.second(), time.msec()));
    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}

//设置系统日期的秒
bool MDateTime::setSystemSecond  ( int second)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wSecond  = second;

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QTime time = QTime::currentTime();
    QDateTime dt(QDate::currentDate(),QTime(time.hour(), time.minute(), second, time.msec()));
    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}

//设置系统日期的毫秒
bool MDateTime::setSystemMSec    ( int msec)
{
    SYSTEMTIME systemDateTime;
    GetLocalTime(&systemDateTime);
    systemDateTime.wMilliseconds = msec;

    bool rlt = SetLocalTime(&systemDateTime);
    if( rlt == false )
        return false;

    QTime time = QTime::currentTime();
    QDateTime dt(QDate::currentDate(),QTime(time.hour(), time.minute(), time.second(), msec));
    QMutexLocker locker(&_MDateTime_Mutex);
    _MDateTime_PerformanceStartCount = (QueryPerformanceCounter(&_MDateTime_litmp),   _MDateTime_litmp.QuadPart);
    _MDateTime_PerformancestartDateTime_ns = (dt.toMSecsSinceEpoch()*1000000); // 纳秒
    _MDateTime_PerformancestartDateTime_us = (dt.toMSecsSinceEpoch()*1000);    // 微秒
    _MDateTime_PerformancestartDateTime_ms = (dt.toMSecsSinceEpoch());         // 毫秒

    return true;
}

qint64 MDateTime::currentMSecsSinceEpoch()
{
    LARGE_INTEGER litmp;
    QueryPerformanceCounter(&litmp);
    QMutexLocker locker(&_MDateTime_Mutex);
    return qint64( (qint64)1000 * (litmp.QuadPart - _MDateTime_PerformanceStartCount) / _MDateTime_PerformanceFrequency + _MDateTime_PerformancestartDateTime_ms );
}

qint64 MDateTime::currentUSecsSinceEpoch()
{
    LARGE_INTEGER litmp;
    QueryPerformanceCounter(&litmp);
    QMutexLocker locker(&_MDateTime_Mutex);
    return qint64( (qint64)1000000 * (litmp.QuadPart - _MDateTime_PerformanceStartCount) / _MDateTime_PerformanceFrequency + _MDateTime_PerformancestartDateTime_us );
}

qint64 MDateTime::currentNSecsSinceEpoch()
{
    LARGE_INTEGER litmp;
    QueryPerformanceCounter(&litmp);
    QMutexLocker locker(&_MDateTime_Mutex);
    return qint64( (qint64)1000000000 * (litmp.QuadPart - _MDateTime_PerformanceStartCount) / _MDateTime_PerformanceFrequency + _MDateTime_PerformancestartDateTime_ns );
}

MDateTime MDateTime::currentDateTime()
{
    return fromNSecsSinceEpoch(currentNSecsSinceEpoch());
}

MDateTime MDateTime::fromMSecsSinceEpoch(qint64 msecs)
{
    QDateTime dt = QDateTime::fromMSecsSinceEpoch(msecs);
    return MDateTime(dt);
}

MDateTime MDateTime::fromUSecsSinceEpoch(qint64 usecs)
{
    double mmm_uuu = (usecs % 1000000) / 1000.0;
    QDateTime dt = QDateTime::fromMSecsSinceEpoch(usecs / 1000);
    MDateTime mdt(dt);
    MDate mdtDate = mdt.date();
    MTime mt = mdt.time();
    mt.setHMS(mt.hour(), mt.minute(), mt.second(), mmm_uuu);
    return MDateTime(mdtDate, mt);
}

MDateTime MDateTime::fromNSecsSinceEpoch(qint64 nsecs)
{
    double mmm_uuu_nnn = (nsecs % 1000000000) / 1000000.0;
    QDateTime dt = QDateTime::fromMSecsSinceEpoch(nsecs / 1000000);
    MDateTime mdt(dt);
    MDate mdtDate = mdt.date();
    MTime mt = mdt.time();
    mt.setHMS(mt.hour(), mt.minute(), mt.second(), mmm_uuu_nnn);
    return MDateTime(mdtDate, mt);
}

MDate MDateTime::date()
{
    return QDateTime::date();
}

MTime MDateTime::time()
{
    return m_time;
}

QString MDateTime::toString(const QString &format) const
{
    QString rlt = QDateTime::toString(format);

    QRegExp reg("[uU]+");
    int pos = reg.indexIn(rlt,0);
    if( pos>=0 )
    {
        double m_ms = MTime(m_time).getInteralMsVal();
        int len = reg.matchedLength();
        switch( len )
        {
        case 0: rlt.replace(pos, len, QString("%1").arg(int(m_ms*0.001+0.5), len, 10, QLatin1Char('0'))); break;
        case 1: rlt.replace(pos, len, QString("%1").arg(int(m_ms*0.01+0.5), len, 10, QLatin1Char('0'))); break;
        case 2: rlt.replace(pos, len, QString("%1").arg(int(m_ms*0.1+0.5), len, 10, QLatin1Char('0'))); break;
        case 3: rlt.replace(pos, len, QString("%1").arg(int(m_ms*1+0.5), len, 10, QLatin1Char('0'))); break;
        case 4: rlt.replace(pos, len, QString("%1").arg(int(m_ms*10+0.5), len, 10, QLatin1Char('0'))); break;
        case 5: rlt.replace(pos, len, QString("%1").arg(int(m_ms*100+0.5), len, 10, QLatin1Char('0'))); break;
        case 6: rlt.replace(pos, len, QString("%1").arg(int(m_ms*1000+0.5), len, 10, QLatin1Char('0'))); break;
        case 7: rlt.replace(pos, len, QString("%1").arg(int(m_ms*10000+0.5), len, 10, QLatin1Char('0'))); break;
        case 8: rlt.replace(pos, len, QString("%1").arg(int(m_ms*100000+0.5), len, 10, QLatin1Char('0'))); break;
        default:rlt.replace(pos, len, QString("%1").arg(int(m_ms*1000000+0.5), len, 10, QLatin1Char('0'))); break;
        }
    }
    return rlt;
}

qint64 MDateTime::toUSecsSinceEpoch()
{
    return toMSecsSinceEpoch()/1000*1000000+int(m_time.getInteralMsVal()*1000+0.5);
}

qint64 MDateTime::toNSecsSinceEpoch()
{
    return toMSecsSinceEpoch()/1000*1000000000+int(m_time.getInteralMsVal()*1000000+0.5);
}
